package com.zytlifeservice.service.pay;

import com.google.gson.Gson;
import com.qianmi.open.api.ApiException;
import com.qianmi.open.api.OpenClient;
import com.qianmi.open.api.QianmiRequest;
import com.qianmi.open.api.QianmiResponse;
import com.qianmi.open.api.domain.elife.OrderDetailInfo;
import com.qianmi.open.api.domain.elife.TicketOrder;
import com.qianmi.open.api.domain.elife.TicketTrade;
import com.qianmi.open.api.qmcs.QmcsClient;
import com.qianmi.open.api.qmcs.channel.ChannelException;
import com.qianmi.open.api.qmcs.handler.MessageHandler;
import com.qianmi.open.api.qmcs.message.Message;
import com.qianmi.open.api.qmcs.message.MessageStatus;
import com.qianmi.open.api.request.FinanceGetAcctInfoRequest;
import com.qianmi.open.api.response.FinanceGetAcctInfoResponse;
import com.qianmi.open.api.response.TokenResponse;
import com.qianmi.open.api.tool.util.OAuthUtils;
import com.qianmi.open.api.tool.util.QianmiContext;
import com.zytlifeservice.config.QianmiConfig;
import com.zytlifeservice.domain.User;
import com.zytlifeservice.domain.find.Integral;
import com.zytlifeservice.domain.find.IntegralOrder;
import com.zytlifeservice.domain.pay.*;
import com.zytlifeservice.exception.UserException;
import com.zytlifeservice.repository.pay.*;
import com.zytlifeservice.response.TicketResponse;
import com.zytlifeservice.service.UserService;
import com.zytlifeservice.service.find.CommodityService;
import com.zytlifeservice.service.find.IntegralService;
import com.zytlifeservice.util.TextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by MJS on 2017/5/31.
 */
@Service
public class PublicService {
    @Autowired
    QianmiConfig qianmiConfig;

    @Value("${bm_callback}")
    private String bm_callback_url;

    @Autowired
    private OpenClient client;

    private Logger logger = LoggerFactory.getLogger(PublicService.class);

    @Autowired
    private AlipayOrderRepository alipayOrderRepository;

    @Autowired
    private AlipayService alipayService;

    @Autowired
    private IntegralService integralService;

    @Autowired
    private UserService userService;

    @Autowired
    private CommodityService commodityService;

    @Autowired
    private TrainRechargeOrderRepository trainRechargeOrderRepository;

    @Autowired
    private AirplaneRechargeOrderRepository airplaneRechargeOrderRepository;

    @Autowired
    private WxPayOrderRepository wxPayOrderRepository;

    @Autowired
    private PassengersRepository passengersRepository;

    @Autowired
    private WxPayService wxPayService;
    private QmcsClient qmcsClient;


    public boolean querySum(String price) {
        FinanceGetAcctInfoRequest req = new FinanceGetAcctInfoRequest();
        try {
            FinanceGetAcctInfoResponse response = execute(req);
            if (response.isSuccess()) {
                String sum = response.getAcctInfo().getBalance();
                float balance = Float.parseFloat(sum);
                float cost = Float.parseFloat(price);
                if (cost + 10 < balance) {
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }

    /*
    解析公共参数
     */
    public void parseResponse(BaseQmOrder order, OrderDetailInfo orderDetailInfo) {
        order.setPayResult(BaseQmOrder.STATUS_WAIT);
        order.setSaleAmount(orderDetailInfo.getSaleAmount());
        order.setItemName(orderDetailInfo.getItemName());
        order.setOrderTime(orderDetailInfo.getOrderTime());
        order.setOrderCost(orderDetailInfo.getOrderCost());
        order.setSaleAmount(orderDetailInfo.getSaleAmount());
        order.setBillId(orderDetailInfo.getBillId());
        order.setSupId(orderDetailInfo.getSupId());
        order.setPayState(orderDetailInfo.getPayState());
        order.setUserCode(orderDetailInfo.getUserCode());
        order.setFailReason(BaseQmOrder.STATUS_WAIT);
//        addScore(order);  在斑马回调的时候，再执行积分添加操作
    }

    public void parseTicketOrderResponse(BaseAirplaneAndTrianOrder order, TicketTrade ticketTrade) {
        //暂时没有需要更新的内容。


    }

    public void setBaseOrderType(BaseQmOrder order) {
        int type = 0;
        if (order instanceof MobileRechargeOrder) {
            type = BaseQmOrder.TYPE_MOBILE_RECHARGE;
        } else if (order instanceof BroadBandAndPhoneDomain) {
            type = BaseQmOrder.TYPE_GHKD_RECHARGE;
        } else if (order instanceof FlowRechargeOrder) {
            type = BaseQmOrder.TYPE_MOBILE_FLOW;
        } else if (order instanceof WiredTvRechargeOrder) {
            type = BaseQmOrder.TYPE_CATV;
        } else if (order instanceof WaterCoalOrder) {
            WaterCoalOrder waterCoalOrder = (WaterCoalOrder) order;
            if (WaterCoalOrder.TYPE_ELECTRIC.equals(waterCoalOrder.getType())) {
                type = BaseQmOrder.TYPE_ELECTRIC;
            } else if (WaterCoalOrder.TYPE_COAL.equals(waterCoalOrder.getType())) {
                type = BaseQmOrder.TYPE_COAL;
            } else if (WaterCoalOrder.TYPE_WATER.equals(waterCoalOrder.getType())) {
                type = BaseQmOrder.TYPE_WATER;
            }
        }
        order.setOrderType(type);
    }

    public void addScore(BaseQmOrder order) {
        //这里，得到用户的开销，进行插入操作
        Integral integral = new Integral();
        String type = "";
        if (order instanceof MobileRechargeOrder) {
            type = Integral.TYPE_MOBILE_RECHARGE;
        } else if (order instanceof BroadBandAndPhoneDomain) {
            type = Integral.TYPE_GHKD_RECHARGE;
        } else if (order instanceof FlowRechargeOrder) {
            type = Integral.TYPE_MOBILE_FLOW;
        } else if (order instanceof WiredTvRechargeOrder) {
            type = Integral.TYPE_CATV;
        } else if (order instanceof WaterCoalOrder) {
            WaterCoalOrder waterCoalOrder = (WaterCoalOrder) order;
            if (WaterCoalOrder.TYPE_ELECTRIC.equals(waterCoalOrder.getType())) {
                type = Integral.TYPE_ELECTRIC;
            } else if (WaterCoalOrder.TYPE_COAL.equals(waterCoalOrder.getType())) {
                type = Integral.TYPE_COAL;
            } else if (WaterCoalOrder.TYPE_WATER.equals(waterCoalOrder.getType())) {
                type = Integral.TYPE_WATER;
            }
        }
        integral.setGtypeId(type);
        integral.setUserId(order.getUserId());
        Float money = Float.parseFloat(order.getSaleAmount());
        integralService.addIntegral(integral, money);
    }

    public BaseQmOrder refund(BaseQmOrder order, QianmiResponse response) {
        order.setFailReason(response.getSubMsg());
        order.setPayResult(BaseQmOrder.STATUS_FAIL);

        AlipayOrder byOutTradeNo = alipayOrderRepository.findByOutTradeNo(order.getOutTradeNo());
        byOutTradeNo.setRefundReason(response.getSubMsg());
        alipayService.reFund(byOutTradeNo, "");
        return order;
    }

    //测试事务操作的完整性
    @Transactional
    public int buyGood(IntegralOrder integralOrder) {
        int res = 0;
        res = commodityService.minusGoodCount(integralOrder.getCount(), integralOrder.getCommodityId());
        if (res > 0) {
            res = userService.updateToIntegral(integralOrder.getUserId(), integralOrder.getIntegral(), Integral.TYPE_MINUS);
        }
        return res;
    }

    public OpenClient getBMClient() {
        return client;
    }

    public <T extends QianmiResponse> T execute(QianmiRequest<T> request) throws ApiException {
        logger.info("accessToken ={}", qianmiConfig.getAccessToken());
        return client.execute(request, qianmiConfig.getAccessToken());
    }


    /*
    更新bm token
     */
    public TokenResponse updateToken() {
        logger.info("更新token值");
        try {
            QianmiContext qianmiContext = OAuthUtils.refreshToken(qianmiConfig.getApp_key(), qianmiConfig.getApp_secret(), qianmiConfig.getRefreshToken());
            TokenResponse tokenResponse = qianmiContext.getTokenResponse();
            setToken(tokenResponse);
            return tokenResponse;
        } catch (ApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    private void setToken(TokenResponse tokenResponse) {
        qianmiConfig.updateAccessToken(tokenResponse.getAccessToken());
        qianmiConfig.updateRefreshToken(tokenResponse.getRefreshToken());
    }

    public AlipayOrder generateAlipayOrder(User one, String subjectName, String rechargeAmount, String outTradeNo, int orderType) {
        AlipayOrder alipayOrder = new AlipayOrder();
        alipayOrder.setStoreId(one.getStoreId());
        alipayOrder.setSubject(subjectName);//对应的后台的信息
        alipayOrder.setOutTradeNo(outTradeNo);
        alipayOrder.setTotalAmount(rechargeAmount);
        alipayOrder.setUserId(one.getUserId());
        alipayOrder.setType(orderType);
        alipayOrder.setOrderStatus(AlipayOrder.ORDER_WAIT);
        return alipayOrder;
    }

    public WxPayOrder generateWxpayOrder(User one, String subjectName, String ip, String rechargeAmount, String outTradeNo, int orderType) {
        WxPayOrder wxPayOrder = new WxPayOrder();
        wxPayOrder.setBody(subjectName);
        wxPayOrder.setOutTradeNo(outTradeNo);
        if (TextUtil.isEmpty(ip)) {
            ip = "127.0.0.1";
        }
        wxPayOrder.setSpbill_create_ip(ip);
//        rechargeAmount = "0.01";
        float parseFloat = Float.parseFloat(rechargeAmount);
        int price = (int) (parseFloat * 100);
        wxPayOrder.setTotal_fee(String.valueOf(price));
        wxPayOrder.setUserId(one.getUserId());
        wxPayOrder.setType(orderType);
        wxPayOrder.setStoreId(one.getStoreId());
        wxPayOrder.setOrderStatus(WxPayOrder.ORDER_WAIT);
        return wxPayOrder;
    }

    public String getBmCallbackUrl() {
        return bm_callback_url;
    }


    public String getBmMsgUrl() {
        return qianmiConfig.getBm_msg_url();
    }


    public void initBMMsg() {
        logger.info("初始化斑马消息");
        qmcsClient = new QmcsClient(qianmiConfig.getApp_key(), qianmiConfig.getApp_secret(), "zyt_life_service");
        qmcsClient.setMessageHandler(new MessageHandler() {
            @Override
            public void onMessage(Message message, MessageStatus messageStatus) throws Exception {
                try {
                    //以下仅为示例代码,实际业务处理根据自身需要开发
                    System.out.println(message.getTopic());
                    System.out.println(message.getContent());
                    logger.error("bmMsg getTopic=" + message.getTopic());
                    logger.error("bmMsg getContent=" + message.getContent());
                    logger.error("bmMsg getPubKey =" + message.getPubAppKey());
                    //根据订单的状态，更新到本地数据库。将结果返回。
                    //拿到是飞机票还是火车票
                    if ("qianmi_elife_ticketStateChange".equals(message.getTopic())) {
                        Gson gson = new Gson();
                        TicketResponse ticketResponse = gson.fromJson(message.getContent(), TicketResponse.class);
                        logger.error("response=" + ticketResponse);
                        String tradeNo = ticketResponse.getTrade_no();

                        //得到票务订单的实体。
                        BaseAirplaneAndTrianOrder order = getTicketOrder(tradeNo);
                        logger.error("baseTicketOrder={}", order);
                        //这里的通知，可能回出现重复通知的情况，所以要先校验有没有被处理过。
                        if (order != null) {
                            String state = ticketResponse.getTicket_state();
                            if ("9".equals(state)) {
                                //这里说明订单失败，更新失败原因，同时走退款流程.

                                //这里是否需要更新子订单的状态。主要是体现在退票时的多一层判断，只有成功的时候才需要退票。
                                //直接根据状态来看。
                                order.setPayResult(BaseAirplaneAndTrianOrder.STATUS_FAIL);
                                order.setFailReason(ticketResponse.getReason());
                                //退款
                                refundPay(order.getOutTradeNo(), "");
                            } else if ("1".equals(state)) {
                                //订单成功，处理订单结果。
                                order.setPayResult(BaseAirplaneAndTrianOrder.STATUS_SUCCESS);
                            }
                            updateTicketResponse(order);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    messageStatus.fail();//消息处理失败,需要服务端重新推送
                }
            }
        });
        try {
            qmcsClient.connect(qianmiConfig.getBm_msg_url());
        } catch (ChannelException e) {
            e.printStackTrace();
        }
    }

    public void closeQmCsClient() {
        qmcsClient.close();
    }

    private void updateTicketResponse(BaseAirplaneAndTrianOrder order) {
        if (order instanceof TrianRechargeOrder) {
            trainRechargeOrderRepository.save((TrianRechargeOrder) order);
        } else if (order instanceof AirplaneRechargeOrder) {
            airplaneRechargeOrderRepository.save((AirplaneRechargeOrder) order);
        }
    }

    private BaseAirplaneAndTrianOrder getTicketOrder(String tradeNo) {
        List<BaseAirplaneAndTrianOrder> list = new ArrayList<>();
        list.add(trainRechargeOrderRepository.findByTradeNo(tradeNo));
        list.add(airplaneRechargeOrderRepository.findByTradeNo(tradeNo));
        for (BaseAirplaneAndTrianOrder order : list) {
            if (order != null) {
                return order;
            }
        }
        return null;
    }

    /*
    解析票务订单
     */
    public void parseTicketsResponse(long Order_id, String outTradeNo, List<TicketOrder> ticketOrders, int type, String ctime) {
        Passengers passengers = new Passengers();  //子订单的内容。
        for (int i = 0; i < ticketOrders.size(); i++) {
            passengers.setOrder_id(Order_id);
            passengers.setOutTradeNo(outTradeNo);
            passengers.setSeatType(ticketOrders.get(i).getSeatType());
            passengers.setIdcardNo(ticketOrders.get(i).getIdcardNo());
            passengers.setContactName(ticketOrders.get(i).getPassengerName());
            passengers.setContactTel(ticketOrders.get(i).getPassengerTel());
            passengers.setItemId(ticketOrders.get(i).getItemId());
            passengers.setOrderNo(ticketOrders.get(i).getOrderNo());
            passengers.setTicketNo(ticketOrders.get(i).getTicketNo());
            passengers.setTitle(ticketOrders.get(i).getTitle());
            passengers.setPassengersType(type);
            passengers.setCreateDate(ctime);
            passengers.setPayCash(ticketOrders.get(i).getPayCash());
            passengersRepository.save(passengers);
        }
    }

    public void refundPay(String outTradeNo, String refund_free) {
        AlipayOrder alipayOrder = alipayOrderRepository.findByOutTradeNo(outTradeNo);
        logger.error("alipayOrder ={}", alipayOrder);
        if (alipayOrder != null) {
            alipayOrder.setRefundReason("千米订单失败");
            alipayService.reFund(alipayOrder, refund_free);
        } else {
            WxPayOrder wxPayOrder = wxPayOrderRepository.findByOutTradeNo(outTradeNo);
            logger.error("wxPayOrder = {}", wxPayOrder);
            if (wxPayOrder != null) {
                wxPayOrder.setRefundReason("千米订单失败");
                wxPayService.refund(wxPayOrder, refund_free);
            } else {
                throw new UserException("订单不存在", 202);
            }
        }
    }
}
